<?php
error_reporting(0);
date_default_timezone_set("PRC");
include "./sqldb.php";

class WAF extends MySQLDB{
    // sql注入、xss攻击、伪协议等
    function check_threat($files_json_path, $data){
        $uri = $this->get_request_uri();
        // echo "正在对 $uri 进行安全检测</br>";
        $ip = $this->get_client_ip();
        $method = $this->get_request_method();
        for ($i=0; $i < count($files_json_path); $i++) {
            $check_rule = json_decode(file_get_contents($files_json_path[$i]), true);  // 读取文件并将json转为数组
            foreach ($check_rule as $words){
                foreach ($words as $word){
                    // 如果post请求中有内容就检测
                    if (!empty($data)) {
                        if(strstr($data, $word)) {
                            // 存数据库
                            $InSql = "insert waf_info(uri, word, ip, method, time)values('$uri', '$word', '$ip', '$method', now())";
                            $this -> insert_tables($InSql);
                            die("<font color='red'>检测到敏感词: $word, 风险IP为 $ip</font>");
                        }
                    }
                    // 检查get
                    if(strstr($this->get_request_uri(), $word)) {
                        $InSql = "insert waf_info(uri, word, ip, method, time)values('$uri', '$word', '$ip', '$method', now())";
                        $this -> insert_tables($InSql);
                       die("<font color='red'>检测到敏感词: $word, 风险IP为 $ip</font>");
                    }
                    // 检测请求实体(以cookie为例)
                    if(strstr($this->get_request_cookie(), $word)) {
                        $InSql = "insert waf_info(uri, word, ip, method, time)values('$uri', '$word', '$ip', '$method', now())";
                        $this -> insert_tables($InSql);
                       die("<font color='red'>检测到敏感词: $word, 风险IP为 $ip</font>");
                    }
                }
            }
        }
    }
    // 检测文件是否含有木马
    function check_file($file_json, $file_check_path){
        echo "正在对本地文件进行安全检测</br>";
        $file_rule = json_decode(file_get_contents($file_json), true);
        $file = file_get_contents($file_check_path);
        foreach ($file_rule['file'] as $word){
            if(strstr($file, $word)) {
                die("<font color='red'>检测到文件敏感关键词: $word</font></br>");
            }
        }
        // echo "<font color='green'>未发现敏感词</font></br>";
    }
    // 在线动态查看信息  info.html
    function dynamic_info(){
        if (!empty($_GET['arg']) && $_GET['arg'] == 'getInfo') {
            print_r(json_encode($this->Select("select * from waf_info")));
        }
    }
    // iptables策略
    function iptables_rules(){
        // 由于在云服务器操作不便，所有次方法在虚拟机测试
        // 确保有执行管理员命令的权限 修改/etc/sudoers  daemon ALL=(ALL) NOPASSWD:ALL
        // 确保允许访问80端口 iptables -I INPUT -p tcp --dport 80 -j ACCEPT
        // 限制syn的请求速度
        shell_exec("sudo iptables -N syn-flood");
        shell_exec("sudo iptables -A INPUT -p tcp --syn -j syn-flood");
        shell_exec("sudo iptables -A syn-flood -m limit --limit 1/s --limit-burst 4 -j RETURN");
        shell_exec("sudo iptables -A syn-flood -j DROP");
        // 利用recent模块抵御DOS攻击
        // 单个IP最多连接3个会话
        shell_exec("sudo iptables -I INPUT -p tcp --dport 22 -m connlimit --connlimit-above 3 -j DROP");
        // 只要是新的连接请求，就把它加入到SSH列表中
        shell_exec("sudo iptables -I INPUT -p tcp --dport 22 -m state --state NEW -m recent --set --name SSH");
        // 5分钟内尝试次数达到3次，就拒绝提供SSH列表中的这个IP服务。被限制5分钟后即可恢复访问。
        shell_exec("sudo iptables -I INPUT -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 300 --hitcount 3 --name SSH -j DROP");
        // 防止单个ip访问量过大
        shell_exec("sudo iptables -I INPUT -p tcp --dport 80 -m connlimit --connlimit-above 30 -j DROP");
        # 防止DDOS攻击，设定一些数据的限制条件
        // shell_exec("sudo iptables -A INPUT -p tcp --dport 80 -m limit --limit 25/minute --limit-burst 100 -j ACCEPT");
    }
    // 获取uri
    function get_request_uri(){
        return $_SERVER['REQUEST_URI'];
    }
    // 获取ip
    function get_client_ip(){
        return $_SERVER['REMOTE_ADDR'];
    }
    // 获取请求方式
    function get_request_method() {
        return $_SERVER['REQUEST_METHOD'];
	}
    // 获取cookie
    function get_request_cookie() {
        if (!empty($_SERVER['HTTP_COOKIE'])) {
            return $_SERVER['HTTP_COOKIE'];
        }
        return '未获取到cookie';
	}
}

// 规则文件
$sql_json = "./rules/sql.json";
$xss_json = "./rules/xss.json";
$webshell_json = "./rules/webshell.json";
$protocol_json = "./rules/protocol.json";
$file_json = "./rules/file.json";
$serializa_json = "./rules/serialization.json";
// 要检测文件的路径
$file_check_path = "./uploads/muma.png";  
//获取post的data，无论是否是mutipart
$data = file_get_contents('php://input'); 

$files_json_path = [$sql_json, $xss_json, $webshell_json, $protocol_json, $serializa_json];

$waf = new WAF();
// $waf->check_threat($files_json_path, $data);
// $waf->check_file($file_json, $file_check_path);
$waf->dynamic_info();
// $waf->iptables_rules();
